package com.ismarkendenis.dxkeyexchange;

import java.math.BigInteger;
import java.util.Random;

public class Numbers
{
	private BigInteger q = new BigInteger("78243894352230174512518076987873908437111967051827360162185639015633269213871");
	private BigInteger N = new BigInteger("271635811471063539662428296906302361106929196305610456841434279640798597729641397817633846544646442581888340440982675527180266251431009109057096626284009782643399907130125989082304929403781249777327515440708155384472207461720221166584273427148057932692798066712726596892079120156839321494092247968999641787081316251821157148739142675477127870990905998245136149862871052937938099522549635509994096961537766927360330908609589760648566069392965326841504827561277353824783260151168746541215221709993564438424015817991042861217821540706836748816");
	private BigInteger p = new BigInteger("21253843735024208942914005722280415927174304985392674872076808401863336199877507530689905586971139083361977094368797434194316646876411007410264120997257464391634944541488008220328763709859611522015934862480895549533382759188271194679838032023093664758832131033966279069766908187961920797797480754210601409074657883620154111334630002459673343184255648551524801688795467708027998290336513297685457463924396988621352614354280867561177496792137030976669351225888523602504755541370574248427945679069966466170756846408752718701621608022497801652178930289033736827546965503713528032906968131129435046786593189837841810026737");
	private BigInteger g = new BigInteger("1537611182983413765526852379114251437237896075894970233207288525579438283782148407564976086650167445432696727339152065706183025524161597505463922401505596517437248454750833477429456628783266978322477925100862946426379201483168828813207688937363937877823685097787036236007367290179938171199928403315187288603074750585976586149644307878659352542949933870358054036741037889155770046416250815040135070966998951870025130804841520848937788243919475716113099024997469283606506805068498429719230153399707537577924162559205139231892677423324751341168829051809613124232857199308943613928870195406084919348052513634854081090816");
	private BigInteger a = new BigInteger("59267");
	
	public BigInteger calculateQ()
	{
		if(q != null)	
		{
			return q;
		}
		
		Random r = new Random();
		
		q = new BigInteger(256, 99999, r);
		
		return q;
	}
	
	public BigInteger calculateN(BigInteger q)
	{
		if (N != null)
		{
			return N;
		}
		
		Random r = new Random();
		BigInteger pSizedNumber = new BigInteger(2048, r);
		N = pSizedNumber.divide(q);
		N.clearBit(0);
		
		return N;
	}
	
	public BigInteger calculateP(BigInteger q)
	{
		if(p != null)
		{
			return p;
		}
		
		boolean prime = false;
		p = null;
		while (!prime && p.bitLength() != 2048)
		{
			// Get N to calculate a probable prime p
			N = this.calculateN(this.getQ());	
			p = N.multiply(q).add(new BigInteger("1"));
			
			prime = p.isProbablePrime(9999);
		}
		
		return p;
	}
	
	public BigInteger calculateG(BigInteger N, BigInteger q, BigInteger p)
	{
		if (g != null)
		{
			return g;
		}
		
		BigInteger one = new BigInteger("1");
		this.g = new BigInteger("2");
		boolean notFound = true;
		
		while (notFound)
		{
			this.calculateA();
			
			g = this.calculateA().modPow(N, p);
			if(g.compareTo(one) != 0 && 
			   g.modPow(q,p).compareTo(one) == 0)
			{
				notFound = false;
			}
		}
		
		return g;
	}
	
	public BigInteger calculateA()
	{
		if (a != null)
		{
			return a;
		}
		
		Random r = new Random();
		a = new BigInteger(16, r);
		
		return a;
	}
	
	public BigInteger getQ()
	{
		return q;
	}
	
	public BigInteger getN()
	{
		return N;
	}
	
	public BigInteger getP()
	{
		return p;
	}
	
	public BigInteger getG()
	{
		return g;
	}
	
	public BigInteger getA()
	{
		return a;
	}
}
